package org.example.scoresystem_backen.service.impl;

import org.example.scoresystem_backen.entity.Score;
import org.example.scoresystem_backen.mapper.ScoreMapper;
import org.example.scoresystem_backen.service.ScoreService;
import org.example.scoresystem_backen.dto.PageRequest;
import org.example.scoresystem_backen.dto.PageResponse;
import org.example.scoresystem_backen.dto.ScoreDetailDTO;
import org.example.scoresystem_backen.dto.StudentOptionDTO;
import org.example.scoresystem_backen.dto.CourseOptionDTO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.List;

/**
 * 成绩服务实现类
 */
@Service
@Transactional
public class ScoreServiceImpl implements ScoreService {
    
    @Autowired
    private ScoreMapper scoreMapper;
    
    @Override
    public Score createScore(Score score) {
        // 检查该学生该课程是否已有成绩
        if (scoreMapper.existsByStudentIdAndCourseId(score.getStudentId(), score.getCourseId())) {
            throw new RuntimeException("该学生该课程成绩已存在");
        }
        scoreMapper.insert(score);
        return score;
    }

    @Override
    public Score updateScore(Score score) {
        Score existing = scoreMapper.findById(score.getId());
        if (existing == null) {
            throw new RuntimeException("成绩记录不存在");
        }
        scoreMapper.update(score);
        return score;
    }

    @Override
    public void deleteScore(Integer id) {
        Score score = scoreMapper.findById(id);
        if (score == null) {
            throw new RuntimeException("成绩记录不存在");
        }
        scoreMapper.deleteById(id);
    }
    
    @Override
    @Transactional(readOnly = true)
    public Score findById(Integer id) {
        Score score = scoreMapper.findById(id);
        if (score != null) {
            return score;
        }
        throw new RuntimeException("成绩记录不存在");
    }

    @Override
    @Transactional(readOnly = true)
    public List<Score> findAll() {
        return scoreMapper.findAll();
    }

    @Override
    @Transactional(readOnly = true)
    public Page<Score> findAll(Pageable pageable) {
        // MyBatis不直接支持分页，这里简化处理
        List<Score> allScores = scoreMapper.findAll();
        int start = (int) pageable.getOffset();
        int end = Math.min((start + pageable.getPageSize()), allScores.size());
        List<Score> pageContent = allScores.subList(start, end);
        return new PageImpl<>(pageContent, pageable, allScores.size());
    }
    
    @Override
    @Transactional(readOnly = true)
    public List<Score> findByStudentId(Integer studentId) {
        return scoreMapper.findByStudentId(studentId);
    }

    @Override
    @Transactional(readOnly = true)
    public List<Score> findByCourseId(Integer courseId) {
        return scoreMapper.findByCourseId(courseId);
    }

    @Override
    @Transactional(readOnly = true)
    public Score findByStudentIdAndCourseId(Integer studentId, Integer courseId) {
        Score score = scoreMapper.findByStudentIdAndCourseId(studentId, courseId);
        if (score != null) {
            return score;
        }
        throw new RuntimeException("成绩记录不存在");
    }
    
    @Override
    @Transactional(readOnly = true)
    public List<Score> findByClassId(Integer classId) {
        return scoreMapper.findByClassId(classId);
    }

    @Override
    @Transactional(readOnly = true)
    public List<Score> findByClassIdAndCourseId(Integer classId, Integer courseId) {
        return scoreMapper.findByClassIdAndCourseId(classId, courseId);
    }

    @Override
    @Transactional(readOnly = true)
    public List<Score> findByScoreBetween(BigDecimal minScore, BigDecimal maxScore) {
        return scoreMapper.findByScoreBetween(minScore, maxScore);
    }

    @Override
    @Transactional(readOnly = true)
    public List<Score> findByExamDateBetween(LocalDate startDate, LocalDate endDate) {
        return scoreMapper.findByExamDateBetween(startDate, endDate);
    }
    
    @Override
    @Transactional(readOnly = true)
    public BigDecimal calculateAverageScoreByStudentId(Integer studentId) {
        BigDecimal average = scoreMapper.getAverageScoreByStudentId(studentId);
        return average != null ? average : BigDecimal.ZERO;
    }

    @Override
    @Transactional(readOnly = true)
    public BigDecimal calculateAverageScoreByCourseId(Integer courseId) {
        BigDecimal average = scoreMapper.getAverageScoreByCourseId(courseId);
        return average != null ? average : BigDecimal.ZERO;
    }

    @Override
    @Transactional(readOnly = true)
    public BigDecimal calculateAverageScoreByClassId(Integer classId) {
        BigDecimal average = scoreMapper.calculateAverageScoreByClassId(classId);
        return average != null ? average : BigDecimal.ZERO;
    }

    @Override
    @Transactional(readOnly = true)
    public boolean existsByStudentIdAndCourseId(Integer studentId, Integer courseId) {
        return scoreMapper.existsByStudentIdAndCourseId(studentId, courseId);
    }
    
    @Override
    public List<Score> batchImportScores(List<Score> scores) {
        // 批量保存前进行验证
        for (Score score : scores) {
            if (scoreMapper.existsByStudentIdAndCourseId(score.getStudentId(), score.getCourseId())) {
                throw new RuntimeException("学生ID:" + score.getStudentId() +
                    ", 课程ID:" + score.getCourseId() + " 的成绩已存在");
            }
        }
        // MyBatis需要逐个插入
        for (Score score : scores) {
            scoreMapper.insert(score);
        }
        return scores;
    }

    // ========== 分页查询相关方法实现 ==========

    @Override
    @Transactional(readOnly = true)
    public PageResponse<ScoreDetailDTO> findScoreDetailsWithPagination(PageRequest pageRequest) {
        // 验证分页参数
        pageRequest.validate();

        // 查询总记录数
        Long totalCount = scoreMapper.countScoreDetailsWithConditions(pageRequest);

        // 如果没有数据，返回空结果
        if (totalCount == 0) {
            return PageResponse.empty(pageRequest);
        }

        // 查询分页数据
        List<ScoreDetailDTO> scoreDetails = scoreMapper.findScoreDetailsWithPagination(pageRequest);

        // 构建分页响应
        return PageResponse.of(pageRequest, totalCount, scoreDetails);
    }

    @Override
    @Transactional(readOnly = true)
    public PageResponse<ScoreDetailDTO> findScoreDetailsByStudentIdWithPagination(Integer studentId, PageRequest pageRequest) {
        // 验证参数
        if (studentId == null || studentId <= 0) {
            throw new RuntimeException("学生ID不能为空");
        }
        pageRequest.validate();

        // 查询总记录数
        Long totalCount = scoreMapper.countScoreDetailsByStudentIdWithConditions(studentId, pageRequest);

        // 如果没有数据，返回空结果
        if (totalCount == 0) {
            return PageResponse.empty(pageRequest);
        }

        // 查询分页数据
        List<ScoreDetailDTO> scoreDetails = scoreMapper.findScoreDetailsByStudentIdWithPagination(studentId, pageRequest);

        // 构建分页响应
        return PageResponse.of(pageRequest, totalCount, scoreDetails);
    }

    // ========== 增强的CRUD操作实现 ==========

    @Override
    public Score createScoreWithValidation(Score score) {
        // 数据验证
        validateScoreData(score);

        // 检查该学生该课程是否已有成绩
        if (scoreMapper.existsByStudentIdAndCourseId(score.getStudentId(), score.getCourseId())) {
            throw new RuntimeException("该学生该课程成绩已存在");
        }

        // 插入成绩
        scoreMapper.insert(score);
        return score;
    }

    @Override
    public Score updateScoreWithValidation(Score score) {
        // 数据验证
        validateScoreData(score);

        // 检查成绩记录是否存在
        Score existing = scoreMapper.findById(score.getId());
        if (existing == null) {
            throw new RuntimeException("成绩记录不存在");
        }

        // 检查是否与其他记录冲突（学生+课程组合唯一性）
        Score conflictScore = scoreMapper.findByStudentIdAndCourseId(score.getStudentId(), score.getCourseId());
        if (conflictScore != null && !conflictScore.getId().equals(score.getId())) {
            throw new RuntimeException("该学生该课程已有其他成绩记录");
        }

        // 更新成绩
        scoreMapper.update(score);
        return score;
    }

    @Override
    public void deleteScoreWithValidation(Integer id) {
        if (id == null || id <= 0) {
            throw new RuntimeException("成绩ID不能为空");
        }

        Score score = scoreMapper.findById(id);
        if (score == null) {
            throw new RuntimeException("成绩记录不存在");
        }

        scoreMapper.deleteById(id);
    }

    // ========== 选项查询相关方法实现 ==========

    @Override
    @Transactional(readOnly = true)
    public List<StudentOptionDTO> getStudentOptions() {
        return scoreMapper.findStudentOptions();
    }

    @Override
    @Transactional(readOnly = true)
    public List<CourseOptionDTO> getCourseOptions() {
        return scoreMapper.findCourseOptions();
    }

    // ========== 权限验证相关方法实现 ==========

    @Override
    @Transactional(readOnly = true)
    public boolean hasPermissionToAccessScore(Integer studentId, Integer scoreId) {
        if (studentId == null || studentId <= 0 || scoreId == null || scoreId <= 0) {
            return false;
        }

        Score score = scoreMapper.findById(scoreId);
        if (score == null) {
            return false;
        }

        // 学生只能访问自己的成绩
        return score.getStudentId().equals(studentId);
    }

    @Override
    public void validateScoreData(Score score) {
        if (score == null) {
            throw new RuntimeException("成绩数据不能为空");
        }

        if (score.getStudentId() == null || score.getStudentId() <= 0) {
            throw new RuntimeException("学生ID不能为空");
        }

        if (score.getCourseId() == null || score.getCourseId() <= 0) {
            throw new RuntimeException("课程ID不能为空");
        }

        if (score.getScore() == null) {
            throw new RuntimeException("成绩分数不能为空");
        }

        // 验证成绩范围（0-100）
        if (score.getScore().compareTo(BigDecimal.ZERO) < 0 ||
            score.getScore().compareTo(new BigDecimal("100")) > 0) {
            throw new RuntimeException("成绩分数必须在0-100之间");
        }

        // 验证成绩精度（最多两位小数）
        if (score.getScore().scale() > 2) {
            throw new RuntimeException("成绩分数最多保留两位小数");
        }

        // 验证考试日期（不能是未来日期）
        if (score.getExamDate() != null && score.getExamDate().isAfter(LocalDate.now())) {
            throw new RuntimeException("考试日期不能是未来日期");
        }

        // 验证备注长度
        if (score.getRemark() != null && score.getRemark().length() > 500) {
            throw new RuntimeException("备注长度不能超过500个字符");
        }
    }
}
